import { Direction } from "@/constants/Enums";
import ResizeUtil from "./resizeUtil";
import treeToGraphInteractionConfig from "@/api/config/interactionConfigs/treeToGraphInteractionConfig";
import sidebarToGraphInteractionConfig from "@/api/config/interactionConfigs/sidebarToGraphInteractionConfig";
import graphToGraphInteractionConfig from "@/api/config/interactionConfigs/graphToGraphInteractionConfig";

export class GraphShapeUtil {
  static boxSeparator = '::BoxInfo:'

  static isMainShape(shape: UmlShape): boolean {
    return !shape.owner || shape.owner.container.id !== shape.container.id;
  }

  static getMainShape(shape: UmlShape): UmlShape {
    while (shape) {
      if (this.isMainShape(shape)) {
        return shape;
      } else {
        shape = shape.owner;
      }
    }
  }

  static getAbsoluteMainShape(shape: UmlShape): UmlShape {
    while (shape) {
      if (this.isMainShape(shape) && shape.box.position === 'absolute' ) {
        return shape;
      } else {
        shape = shape.owner;
      }
    }
  }
  static getFirstNotInitMainShape(shape:UmlShape):UmlShape{
    while (shape ) {
      if (this.isMainShape(shape) && shape.box.boxX !== null && shape.box.position === 'absolute') {
        return shape;
      } else {
        shape = shape.owner;

      }
    }

  }
  /**
   * 根据鼠标坐标 及目标对象的边界范围确定最近的边
   *
   * @param {number} x 鼠标x坐标
   * @param {number} y 鼠标y坐标
   * @param {number} tx 目标对象的x坐标
   * @param {number} ty 目标对象的y坐标
   * @param {number} tw 目标对象的宽度
   * @param {number} th 目标对象的高度
   * @returns {string}
   * top:上边界
   * bottom:下边界
   * left:左边界
   * right:右边界
   */
  static getClosest(x:number, y:number, tx:number, ty:number, tw:number, th:number):Direction {

    console.log('getClosest');
    const offsetPercent = {
      top: y - ty,
      bottom: ty + th - y,
      left: x - tx,
      right: tx + tw - x
    };
    let minDis = offsetPercent.top;
    let closest = Direction.TOP;
    Object.entries(offsetPercent).forEach(([key, value]) => {
      if (value < minDis) {
        minDis = value;
        closest = key as Direction;
      }
    });
    return closest;
  }

  /**
   * 设置shape的bounds并且更新 box
   * @param shape
   * @param bounds
   */
  static setBounds(shape:UmlShape, bounds:Bounds){
    shape.bounds = bounds;
    ResizeUtil.updateBoxByBounds(shape);

  }

  static updateWaypoints(shape:UmlShape, points:Point[]){
    console.log('points', points);
    shape.box.waypoints = points;

  }

  static parseStName(typeName:string){
    //// const chain = [];
    const item = app.configManager.getTypeNameConfigItem(typeName);
    return item.baseTypeName || item.typeName;

  }

  /**
  * 判断模型树上节点拖动到画布元素上时，是否与目标类型有交互
  *
  * @param {string} typeName 操作元素类型名
  * @param {string} targetType 目标图形类型名
  * @param {string} diagramType 画布类型名
  */
  static hasTreeToGraphInteraction(typeName:string, targetType:string, diagramType:string) {
    let diagramConfig = treeToGraphInteractionConfig[diagramType];
    typeName = this.parseStName(typeName);
    targetType = this.parseStName(targetType);
    //// console.log('diagramConfig', typeName, targetType, diagramType, diagramConfig, diagramConfig && diagramConfig[targetType]);
    return diagramConfig && diagramConfig[targetType] && diagramConfig[targetType].includes(typeName);
  }

  /**
   * 让图表元素可被拖入到画布，生成图标
   * @param {string} sourceType 拖入元素的类型名
   * @param {string} targetType 目标图形类型名
   */
  static canBeDrop (sourceType: string, targetType: string) {
    const targetTypes = [
      'SysMLBlockDefinitionDiagram',
      'SysMLPackageDiagram',
      'SysMLRequirementDiagram',
      'SysMLUseCaseDiagram',
      'SysMLInternalBlockDiagram',
      'SysMLParametricDiagram',
      'SysMLActivityDiagram',
      'SysMLStateMachineDiagram',
      'SysMLSequenceDiagram',
      'RocketTD',
      'SysMLProfileDiagram'
    ];
    const sourceTypes = targetTypes.concat(['RequirementTable', 'SysMLRelationMap']);
    console.log('targetType', sourceType, targetType);
    return targetTypes.includes(targetType) && (sourceTypes.includes(sourceType) || sourceType.includes('Matrix'));
  }

  /**
   * 判断组件区节点拖动到画布元素上时，是否与目标类型有交互
   *
   * @param {string} typeName 操作元素类型名
   * @param {string} targetType 目标图形类型名
   * @param {string} diagramType 画布类型名
   */
  static hasSidebarToGraphInteraction(typeName:string, targetType:string, diagramType:string) {
    let diagramConfig = sidebarToGraphInteractionConfig[diagramType];
    typeName = this.parseStName(typeName);
    targetType = this.parseStName(targetType);
    //// console.log('diagramConfig', diagramConfig, typeName, targetType);
    return diagramConfig && diagramConfig[targetType] && diagramConfig[targetType].includes(typeName);
  }
  
  /**
     * 判断画布元素拖动到画布元素上时，是否与目标类型有交互
     *
     * @param {string} typeName 操作元素类型名
     * @param {string} targetType 目标图形类型名
     * @param {string} diagramType 画布类型名
     */
  static hasGraphToGraphInteraction(typeName:string, targetType:string, diagramType:string) {
    let diagramConfig = graphToGraphInteractionConfig[diagramType];
    typeName = this.parseStName(typeName);
    targetType = this.parseStName(targetType);
    return diagramConfig && diagramConfig[targetType] && diagramConfig[targetType].includes(typeName);
  }

  /**
   * 判断当前图形是否可被设置连线起点
   *
   * @param lineType
   * @param sourceShape
   * @returns {boolean}
   */
  static isValidConnectSource(lineType:string, sourceShape:UmlShape):boolean {
    if (sourceShape) {
      let sourceType = sourceShape.getTypeName();
      let config = app.activeProject.configManager.getConnectConfig()[sourceType];
      if (config) {
        return config.outgoing.includes(lineType);
      } 
    }
    return false;
  }
  
  /**
     * 判断当前图形是否可被设置连线终点
     *
     * @param lineType
     * @param sourceType
     * @param targetType
     * @returns {boolean}
     */
  static isValidConnectTarget(lineType:string, sourceType:string, targetType:string):boolean {
    if (sourceType && targetType) {
      console.log("configManager........", app.activeProject.configManager);
      console.log("configManager.getConnectConfig()........", app.activeProject.configManager.getConnectConfig());
      let outgoingConfig = app.activeProject.configManager.getConnectConfig()[sourceType];
      let incomingConfig = app.activeProject.configManager.getConnectConfig()[targetType];
      console.log('sourceType', lineType, sourceType, targetType, outgoingConfig, incomingConfig);
      if (outgoingConfig && incomingConfig) {
        return outgoingConfig.outgoing.includes(lineType) && incomingConfig.incoming.includes(lineType);
      }
    }
    return false;
  }

  static getBoxKey(shape:UmlShape):string{
    const arr = shape.typeKey.split(this.boxSeparator);
    return arr[arr.length - 1];
  }
  /**
   * 
   */
  /**
   * 获取有交互的父cell,
   * @param typeName 被拖拽的typeName
   * @param currentCell 放置的mainCell
   */
  static getInteractCell(typeName:string, currentCell){
    let resultCell = currentCell;
    const shapeTypeName =  currentCell.umlShape.getTypeName();
    if (shapeTypeName === 'Region' && (typeName === 'PseudostateExitPoint' || typeName === 'PseudostateEntryPoint')){
      resultCell = currentCell.parent.parent;
    }
    return resultCell;

  }

}
